// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;

#include "Symbole.h"
#include "Valeur.h"



/*! \file Arbre.h
    \brief spécification de la classe Symbole
    \author Koelsch + Jamet
    \date 19/12/2012
 */

////////////////////////////////////////////////////////////////////////////////

/*! \class Noeud
    \brief La classe abstraite représentant les Noeuds de base
   
    Classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait. Remarque : la classe ne contient aucun constructeur
  
    Elle contient les méthodes suivantes :
    \li getValeur [pure et virtuelle]
    \li afficher [virtuelle]
    \li ~Noeud [présence d'un destructeur virtuel conseillée dans les classes abstraites]
    \li tradC [pure et virtuelle]
 */
class Noeud {
    
public:
    /*! \fn getValeur() 
        \brief Méthode pure (non implémentée) qui rend la classe abstraite.
    */ virtual Valeur* getValeur() = 0;


    /*! \fn afficher() 
        \brief Pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre
    */ virtual void afficher(unsigned short indentation = 0) 
         {cout << setw(4 * indentation) << " ";}

    /*! \fn ~Noeud() 
        \brief Le destructeur abstrait conseillé pour realiser un héritage.
    */ virtual ~Noeud() {}


    /*! \fn tradC() 
        \brief Permet de traduire du code en code C
    */ virtual void tradC(fstream &fichier) = 0;

    
};

////////////////////////////////////////////////////////////////////////////////

/*! \class NoeudSeqInst
    \brief La classe représentant les Noeuds d'instruction.
   
    Cette classe permet de représenter les Noeuds d'instruction lus dans le programme
    Elle a autant de fils qu'il y a d'instructions dans la séquence.
  
    Elle contient les méthodes suivantes :
    \li NoeudseqInst
    \li ~NoeudseqInst
    \li getValeur 
    \li afficher
    \li tradC 

    Elle contient egalement un attribut tabInst de type vector<Noeud *> qui permet de conserver les instructions recontrées.
 */

class NoeudSeqInst : public Noeud {
public:
    /*! \fn NoeudSeqInst() 
        \brief Construit une séquence d'instruction vide.
     */ NoeudSeqInst();

    /*! \fn ~NoeudSeqInst() 
        \brief Necessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudSeqInst() {}

          
    /*! \fn getValeur() 
        \brief Évalue chaque instruction de la séquence.
     */ Valeur* getValeur();


    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche la séquence d'instructions sur l'affichage pricipal.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);


    /*! \fn ajouteInstruction(Noeud* instruction) 
        \brief Ajoute une instruction au tableau tabInst (représente la suite d'instructions rencontrées).
        \param instruction - Un pointeur sur le noeud de l'instruction à ajouter.
     */ void ajouteInstruction(Noeud* instruction);

    /*! \fn tradC() 
        \brief Permet de traduire du code en code C
     */ void tradC(fstream &fichier);

private:

    /*! \var vector<Noeud *> tabInst
        \brief Pour stocker les instructions de la séquence.
     */ vector<Noeud *> tabInst;
};

////////////////////////////////////////////////////////////////////////////////

/*! \class NoeudAffectation
    \brief La classe représentant les Noeuds d'affectation.
   
    Cette classe permet de représenter les Noeuds d'affectation lus dans le programme
    Elle est composée de 2 fils : la variable et l'expression qu'on lui affecte
  
    Elle contient les méthodes suivantes :
    \li NoeudAffectation
    \li ~NoeudAffectation
    \li getValeur 
    \li afficher
    \li tradC 

    Elle contient deux attributs :
    \li variable de type Noeud *  - Permet de conserver la variable a attribuer.
    \li expression de type Noeud * - Permet de connaitre la valeur à attribuer.
 */
class NoeudAffectation : public Noeud {
    
public:
    /*! \fn NoeudAffectation(Noeud* variable, Noeud* expression) 
        \brief Construit une affectation.
        \param variable - Variable de type Noeud * qui permet de conserver la variable a attribuer.
        \param expression - Expression de type Noeud * qui permet de connaitre la valeur à attribuer.
     */ NoeudAffectation(Noeud* variable, Noeud* expression); 

    /*! \fn ~NoeudAffectation() 
        \brief Necessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudAffectation() {} 
          
    /*! \fn getValeur() 
        \brief Évalue l'expression et affecte sa valeur à la variable.
     */ Valeur* getValeur(); 
          
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche la séquence d'affectation.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);


    /*! \fn tradC() 
        \brief Permet de traduire du code en code C
     */ void tradC(fstream &fichier);

private:
    /*! \var Noeud* variable
        \brief Pour conserver la variable à modifier à portée de main.
     */ Noeud* variable;
          
    /*! \var Noeud* expression
        \brief Pour obtenir la valeur à attribuer à la variable.
     */ Noeud* expression;
};

////////////////////////////////////////////////////////////////////////////////

/*! \class NoeudOperateurBinaire
    \brief La classe représentant les Noeuds d'opérateur binaire.
   
    Cette classe permet de représenter les Noeuds d'affectation lus dans le programme
    Elle est composée de 2 fils : l'opérande gauche et l'opérande droit
  
    Elle contient les méthodes suivantes :
    \li NoeudOperateurBinaire
    \li ~NoeudOperateurBinaire
    \li getValeur 
    \li afficher
    \li tradC 

    Elle contient trois attributs :
    \li operateur de type Symbole - l'opérateur à utiliser(+-/ *).
    \li operandeDroit de type Noeud * - La partie droite de l'opération.
    \li operandeGauche de type Noeud * - La partie gauche de l'opération.
 */

class NoeudOperateurBinaire : public Noeud {
public:
   /*!  \fn NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit) 
        \brief Construit une opération binaire : operandeGauche operateur OperandeDroit.
        \param operateur - Variable de type Symbole qui est l'opérateur (+-/ *).
        \param operandeGauche - Variable de type Noeud * qui permet de connaitre la partie gauche de l'opération.
        \param operandeDroit - Expression de type Noeud * qui permet de connaitre la partie droite de l'opération.
     */ NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);

    /*! \fn ~NoeudOperateurBinaire() 
        \brief Necessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudOperateurBinaire() {}
          
          
    /*! \fn getValeur() 
        \brief Évalue l'operande gauche, l'operande droit et applique l'opérateur.
     */ Valeur* getValeur(); 
    
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche l'opérateur binaire.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0); // affiche l'opération


    /*! \fn tradC() 
        \brief Permet de traduire du code en code C
     */ void tradC(fstream &fichier);

private:
    /*! \var Symbole operateur
        \brief Variable de type Symbole qui est l'opérateur (+-/ *).
     */ Symbole operateur;
          
    /*! \var Noeud* operandeGauche
        \brief Variable de type Noeud * qui permet de connaitre la partie gauche de l'opération.
     */ Noeud* operandeGauche;
          
    /*! \var Noeud* operandeDroit
        \brief Expression de type Noeud * qui permet de connaitre la partie droite de l'opération.
     */ Noeud* operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
/*! \class NoeudSi
    \brief La classe représentant les Noeuds "si".
   
    Cette classe permet de représenter les Noeuds conditionnels lus dans le programme
    Elle est composée de 2 tableaux contenant respectivement les conditions et les séquences d'instruction. 
    On évalue la séquence dans le cas ou la condition est vraie. 
   
    Elle contient les méthodes suivantes :
    \li NoeudSi
    \li ~NoeudSi
    \li getValeur 
    \li afficher
    \li ajoute
    \li tradC 

    Elle contient deux attributs :
    \li vectCond de type vector <Noeud*> - Le tableau contenant toutes les conditions.
    \li vectSeqInst de type vector <Noeud*> - Le tableau contenant tous les NoeudSeqInst.
 */
class NoeudSi : public Noeud {
public:
    
    /*! \fn NoeudSi()
        \brief Construit une instruction "si" vide.
     */ NoeudSi();

    /*! \fn ~NoeudSi()
        \brief Nécessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudSi() {}
          
          
    /*! \fn getValeur() 
        \brief Évalue l'expression et affecte sa valeur à la variable.
     */ Valeur* getValeur();
    
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche le si.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);
          
          
    /*! \fn ajoute(Noeud* cond, Noeud* seq)
        \brief Ajoute une condition et une séquence d'instruction aux tableaux.
        \param cond - la condition à rajouter au tableau de conditions.
        \param seq - la séquence d'instruction (seqInst) à rajouter au tableau de séquences d'instructions.
     */ void ajoute(Noeud* cond, Noeud* seq);

    /*! \fn tradC() 
        \brief Permet de traduire du code en code ada
     */ void tradC(fstream &fichier) ;

private:
    /*! \var vector <Noeud*> vectCond
        \brief Variable de type vector <Noeud*> qui est le tableau de conditions.
     */ vector <Noeud*> vectCond;
          
    /*! \var vector <Noeud*> vectSeqInst
        \brief Variable de type vector <Noeud*> qui est le tableau d'instructions.
     */ vector <Noeud*> vectSeqInst;
};



////////////////////////////////////////////////////////////////////////////////
/*! \class NoeudTq
    \brief La classe représentant les Noeuds "tant que".
   
    Cette classe permet de représenter l'instruction "while" lus dans le programme
    Elle est composée de 2 fils : condition qui vérifie si oui (condition == vrai) ou non (condition == false) il faut boucler
    et seqTq à effectuer tant que la condition est vraie. 
   
    Elle contient les méthodes suivantes :
    \li NoeudTq
    \li ~NoeudTq
    \li getValeur 
    \li afficher
    \li tradC 

    Elle contient deux attributs :
    \li condition de type Noeud* - La condition à évaluer.
    \li seqTq de type Noeud* - La séquence à éxecuter si la condition est vérifiée.
 */

class NoeudTq : public Noeud {
public:
    /*! \fn NoeudTq(Noeud* condition, Noeud* seqTq)
        \brief Construit une instruction tant que.
        \param condition - La condition de la boucle.
        \param seqTq - La séquence d'instruction à effectuer.
     */ NoeudTq(Noeud* condition, Noeud* seqTq); 

          
          
    /*! \fn ~NoeudTq()
        \brief Nécessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudTq() {}
          
          
    /*! \fn getValeur()
        \brief Évalue la condition.
     */ Valeur* getValeur(); // évalue la condition 
    
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche le tant que.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);

    /*! \fn tradC() 
        \brief Permet de traduire du code en code C
     */ void tradC(fstream &fichier);

private:
    /*! \var Noeud* condition
        \brief Variable de type Noeud* qui est la condition.
     */ Noeud* condition;
          
          
    /*! \var Noeud* seqTq
        \brief Variable de type Noeud* qui est la séquence d'instructions.
     */ Noeud* seqTq;
};

////////////////////////////////////////////////////////////////////////////////
/*! \class NoeudRepeter
    \brief La classe représentant les Noeuds "Repeter" (do while).
   
    Cette classe permet de représenter les instructions "do while" lues dans le programme
  
    !!! Tq consiste en un "while" (effectuer si condition = vraie), Repeter effectue puis compare la condition. !!!
  
    Elle est composée de 2 fils : condition qui vérifie si oui (condition == vrai) ou non (condition == false) il faut boucler
    et seqTq à effectuer tant que la condition est vraie. 
   
    Elle contient les méthodes suivantes :
    \li NoeudRepeter
    \li ~NoeudRepeter
    \li getValeur 
    \li afficher
    \li tradC 

    Elle contient deux attributs :
    \li condition de type Noeud* - La condition à évaluer.
    \li seqTq de type Noeud* - La séquence à éxecuter si la condition est vérifiée.
 */

class NoeudRepeter : public Noeud {
    // classe pour représenter un noeud "Lire"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    
    /*! \fn NoeudTq(Noeud* seqRep, Noeud* condition)
        \brief Construit une instruction Repeter.
        \param condition - La condition de la boucle.
        \param seqRep - La séquence d'instruction à effectuer.
     */ NoeudRepeter(Noeud* seqRep, Noeud* condition); // construit une instruction repeter

    /*! \fn ~NoeudRepeter()
        \brief Nécessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudRepeter() {}
          
    /*! \fn getValeur()
        \brief Évalue la condition.
     */ Valeur* getValeur();
    
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche le repeter.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);

    /*! \fn tradC() 
        \brief Permet de traduire du code en code ada [Non implementée pour cette classe]
     */ void tradC(fstream &fichier) ;
private:
    /*! \var Noeud* condition
        \brief Variable de type Noeud* qui est la condition.
     */ Noeud* condition;
          
    /*! \var Noeud* seqRep
        \brief Variable de type Noeud* qui est la séquence d'instructions.
     */ Noeud* seqRep;
};




////////////////////////////////////////////////////////////////////////////////
/*! \class NoeudPour
    \brief La classe représentant les Noeuds "Pour" (for).
   
    Cette classe permet de représenter les instructions "for" lues dans le programme
  
    Elle est composée de 4 fils (également ses attributs): 
    \li affectation de type Noeud* - qui déclare la valeur initiale du compteur.
    \li condition de type Noeud* - qui vérifie si oui (condition == vrai) ou non (condition == false) il faut boucler.
    \li affectationBis de type Noeud* - qui modifie la valeur du compteur.
    \li seqPour de type Noeud* - à effectuer tant que la condition est vraie. 
   
    Elle contient les méthodes suivantes :
    \li NoeudPour
    \li ~NoeudPour
    \li getValeur 
    \li afficher
    \li tradC 

 */
class NoeudPour : public Noeud {
public:
    /*! \fn NoeudPour(Noeud* affectation, Noeud* condition, Noeud* affectationBis, Noeud* seqPour)
        \brief Construit une instruction Pour.
        \param affectation - Déclare la valeur initiale du compteur.
        \param condition - Vérifie si oui (condition == vrai) ou non (condition == false) il faut boucler.
        \param affectationBis - Modifie la valeur du compteur.
        \param seqRep - La séquence d'instruction à effectuer.
     */ NoeudPour(Noeud* affectation, Noeud* condition, Noeud* affectationBis, Noeud* seqPour); 

    /*! \fn ~NoeudPour()
        \brief Nécessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudPour() {}
          
          
    /*! \fn getValeur()
        \brief Évalue la condition.
     */ Valeur* getValeur();
    
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche le pour.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);

    /*! \fn tradC() 
        \brief Permet de traduire du code en code ada [Non implementée pour cette classe]
     */ void tradC(fstream &fichier) ;
private:
    /*! \var Noeud* affectation
        \brief Variable de type Noeud* qui déclare la valeur initiale du compteur.
     */ Noeud* affectation;
          
    /*! \var Noeud* condition
        \brief Variable de type Noeud* qui vérifie si oui (condition == vrai) ou non (condition == false) il faut boucler.
     */ Noeud* condition;
          
    /*! \var Noeud* affectationBis
        \brief Variable de type Noeud* qui modifie la valeur du compteur.
     */ Noeud* affectationBis;
          
    /*! \var Noeud* seqPour
        \brief Variable de type Noeud* qui est la séquence d'instruction à effectuer.
     */ Noeud* seqPour;
};


////////////////////////////////////////////////////////////////////////////////
/*! \class NoeudLire
    \brief La classe représentant les Noeuds "Lire" (cin / scanf / read).
   
    Cette classe permet de représenter les instructions lire lues dans le programme
  
    Elle est composée de 1 fils (également son attribut): 
    \li variable de type Noeud* - qui récupère la valeur saisie.
   
    Elle contient les méthodes suivantes :
    \li NoeudLire
    \li ~NoeudLire
    \li getValeur 
    \li afficher
    \li tradC 

 */
class NoeudLire : public Noeud {
    // classe pour représenter un noeud "Lire"
    // composé de 2 fils : la variable et l'expression qu'on lui affecte
public:
    /*! \fn NoeudLire(Noeud* variable)
        \brief Construit une instruction Lire.
        \param variable - Construit un noeud lire.
     */ NoeudLire(Noeud* variable); 

    /*! \fn ~NoeudLire()
        \brief Nécessaire à cause du destructeur virtuel de la classe Noeud
     */ ~NoeudLire() {}
          
          
    /*! \fn getValeur()
        \brief Lit la valeur saisie au clavier et l'affecte à l'attribut variable.
     */ Valeur* getValeur(); 
    
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche le lire.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);

    /*! \fn tradC() 
        \brief Permet de traduire du code en code C [Non implementée pour cette classe]
     */ void tradC(fstream &fichier) ;
private:
    /*! \var Noeud* variable
        \brief Variable de type Noeud* qui est la variable.
     */ Noeud* variable;
};


////////////////////////////////////////////////////////////////////////////////
/*! \class NoeudEcrire
    \brief La classe représentant les Noeuds "Ecrire" (cout / printf / write).
   
    Cette classe permet de représenter les instructions "ecrire" lues dans le programme
  
    Elle est composée de 1 fils (également son attribut): 
    \li chaine de type Noeud* - qui contient la chaine a afficher.
   
    Elle contient les méthodes suivantes :
    \li NoeudEcrire
    \li ~NoeudEcrire
    \li getValeur 
    \li afficher
    \li tradC 

 */
class NoeudEcrire : public Noeud {
public:
    /*! \fn NoeudEcrire(Noeud* string)
        \brief Construit une instruction Ecrire.
        \param string - Construit un noeud Ecrire avec "string" dans l'attribut chaine.
     */ NoeudEcrire(Noeud* string);
///////////
          //////////////
          /////////////////
    ~NoeudEcrire() {}
    Valeur* getValeur(); // évalue l'expression et affecte sa valeur à la variable
    
    
    /*! \fn afficher(unsigned short indentation=0) 
        \brief Affiche le écrire.
        \param indentation - Le nombre d'espaces à laisser avant de commencer l'affichage.
     */ void afficher(unsigned short indentation = 0);

    /*! \fn tradC() 
        \brief Permet de traduire du code en code C [Non implementée pour cette classe]
     */ void tradC(fstream &fichier) ;


private:
    Noeud* chaine;
};






#endif /* ARBRE_H_ */
